package com.esig.demo.socket;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.SocketException;

public class ClientUI extends JFrame {
    JTextArea mainArea;
    JTextArea sendArea;
    ChatClient1 client;
    JTextField ipArea;
    JButton btnLink;

    public void setClient(ChatClient1 client) {
        this.client = client;
    }

    public ClientUI() {
        super("客户端");
        Container container = getContentPane();
        container.setLayout(new BorderLayout());
        mainArea = new JTextArea();
        JScrollPane mainAreaP = new JScrollPane(mainArea);//为文本区添加滚动条
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        sendArea = new JTextArea(3, 8);
        JButton sendBtn = new JButton("发送");
        sendBtn.addActionListener(new ActionListener() {      //发送按钮
            @Override
            public void actionPerformed(ActionEvent e) {
                client.sendMsg(sendArea.getText());  //客户端发送信息给服务器端
                mainArea.append(sendArea.getText() + "\n");   //添加信息到本地客户端UI
                sendArea.setText("");
            }
        });

        JPanel ipPanel = new JPanel();
        ipPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 10));   //????
        ipPanel.add(new JLabel("服务器："));
        ipArea = new JTextField(12);
        ipArea.setText("127.0.0.1");
        ipPanel.add(ipArea);
        btnLink = new JButton("连接");
        ipPanel.add(btnLink);
        btnLink.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                client = new ChatClient1(ipArea.getText().trim(), ClientUI.this);
                //构造方法 其中ipArea.getText().trim()是上面的127.0.0.1 设置UI，是为了区分多个客户端，我要是做游戏的话，就是通过 玩家对象 区分

                client.start(); //启动线程 这个线程和服务器端的一样原理
                ClientUI.this.setClient(client);  //设置ChatClient1类
            }
        });
        panel.add(sendBtn, BorderLayout.EAST);
        panel.add(sendArea, BorderLayout.CENTER);
        container.add(ipPanel, BorderLayout.NORTH);
        container.add(mainAreaP, BorderLayout.CENTER);
        container.add(panel, BorderLayout.SOUTH);
        setSize(300, 250);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String[] args) {
        ClientUI ui = new ClientUI();
    }
}

class ChatClient1 extends Thread {
    Socket sc;
    BufferedReader in;
    PrintWriter out;
    ClientUI ui;

    public ChatClient1(String ip, ClientUI ui) { //构造方法，设置UI，是为了区分多个客户端，我要是做游戏的话，就是通过 角色对象 区分
        this.ui = ui;
        try {
            sc = new Socket(ip, 6666); //注意这个端口
            System.out.println("已顺利连接到服务器");
            in = new BufferedReader(new InputStreamReader(sc.getInputStream()));
            /**
             * 先实例化BufferedReader缓存流，再实例化InputStreamReader输入流，为了后续能通过readLine()方法一行一行的读数据
             * client.getInputStream() 是获取客户端socket的输入流
             */
            out = new PrintWriter(sc.getOutputStream(), true);
            /**
             * 实例化PrintWrite类 实现通过println()输出任意类型的数据
             * 可能对于游戏来说不太好，因为毕竟tcp协议传字节(byte)为主，他封装了一层，可能占用的空间增大很多
             * 但是也有好处，解决了拆包、粘包问题，就是不会字节没获取完就执行方法，因为读是通过in.readLine()一行一行的读的
             * 不过本身，拆包、粘包问题就不会很难解决，因为int、long等非字符串的字节数是固定的，加上条件判断即可
             * client.getOutputStream() 是获取客户端socket的输出流
             * autoFlush 默认自动确认输出，flush是是否输出
             */
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public void run() {
        String msg = "";
        while (true) {
            try {
                msg = in.readLine();   //一行一行的输入
            } catch (SocketException e) {
                System.out.println(e);
                break;
            } catch (Exception e) {
                System.out.println(e);
            }
            if (msg != null && msg.trim() != "") {
                System.out.println(">>" + msg);
                ui.mainArea.append(msg + "\n");  //接收到消息后，添加到本地客户端UI
            }
        }
    }

    public void sendMsg(String msg) {
        try {
            out.println(msg); //通过PrintWriter类的println()输出信息，然后通过socket线程判断，是否有新增输出信息，后渲染到UI
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
